package at.fhj.pse.domain.service;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import at.fhj.pse.datasource.model.TimeInterval;
import at.fhj.pse.domain.exception.DomainLayerException;
import at.fhj.pse.domain.exception.StacktraceToString;

public class IntervalService {

	private List<TimeInterval> allIntervals;
	private DayIntervalData intervalData;
	private Map<Integer, DayIntervalData> intervalDataMap = new HashMap<Integer, DayIntervalData>();
	private List<DayIntervalData> dayIntervalDataList = new ArrayList<DayIntervalData>();
	private List<DayIntervalData> daysGreaterTenHours;

	private long sumTimeDifference, sumAllocatedTime, sumActualTime;

	public IntervalService(List<TimeInterval> intervals, String usage) {
		if (intervals == null) {
			throw new DomainLayerException("intervals is null", new IllegalArgumentException());
		}
		if (usage == null) {
			throw new DomainLayerException("usage is null", new IllegalArgumentException());
		}
		this.allIntervals = intervals;

		if (usage.equals("day")) {
			try {
				intervalData = new DayIntervalData(this.allIntervals);
			} catch (DomainLayerException ex) {
				throw ex;
			}
		} else {
			sortIntervals();
			calculateData();
		}

	}

	private void sortIntervals() {
		for (TimeInterval ti : this.allIntervals) {
			DayIntervalData iData;
			Calendar cal = Calendar.getInstance();
			cal.setTime(ti.getFrom());
			int dayOfYear = cal.get(Calendar.DAY_OF_YEAR);
			if (!intervalDataMap.containsKey(dayOfYear)) {
				iData = new DayIntervalData();
				iData.addInterval(ti);
				intervalDataMap.put(dayOfYear, iData);
			} else {
				iData = intervalDataMap.get(dayOfYear);
				iData.addInterval(ti);
			}
		}
	}

	private void calculateSums() {
		this.sumTimeDifference = 0;
		this.sumAllocatedTime = 0;
		this.sumActualTime = 0;

		for (DayIntervalData di : this.dayIntervalDataList) {
			this.sumTimeDifference += di.getDifferenceInMinutes();
			this.sumAllocatedTime += di.getAllocatedTimeInMinutes();
			this.sumActualTime += di.getActualTimeInMinutes();
		}
	}

	private void calculateData() {
		for (DayIntervalData iData : intervalDataMap.values()) {
			iData.calculateData();
			this.dayIntervalDataList.add(iData);
			calculateSums();
			Collections.sort(dayIntervalDataList);
		}
	}

	public DayIntervalData getIntervalData() {
		return intervalData;
	}	

	public List<DayIntervalData> getDayIntervalDataList() {
		return dayIntervalDataList;
	}

	public long getSumTimeDifference() {
		return sumTimeDifference;
	}

	public long getSumAllocatedTime() {
		return sumAllocatedTime;
	}


	public long getSumActualTime() {
		return sumActualTime;
	}

	public String getSumTimeDifferenceAsString() {
		String sign = "";
		long differencePositive = Math.abs(this.sumTimeDifference);
		int hours = (int) (differencePositive / 60);
		int minutes = (int) (differencePositive - (hours * 60));

		if (this.sumTimeDifference > 0) {
			sign = "+";
		} else {
			sign = "-";
		}
		return sign + " " + hours + "h " + minutes + "min";
	}

	public String getSumAllocatedTimeAsString() {
		int hours = (int) (this.sumAllocatedTime / 60);
		int minutes = (int) (this.sumAllocatedTime - (hours * 60));
		return hours + "h " + minutes + "min";
	}

	public String getSumActualTimeAsString() {
		int hours = (int) (this.sumActualTime / 60);
		int minutes = (int) (this.sumActualTime - (hours * 60));
		return hours + "h " + minutes + "min";
	}

	public List<DayIntervalData> getDaysGreaterTenHours() {
		daysGreaterTenHours = new ArrayList<DayIntervalData>();
		for(DayIntervalData did : dayIntervalDataList){
			if(did.getActualTimeInMinutes() > 600)
				daysGreaterTenHours.add(did);
		}
		Collections.sort(daysGreaterTenHours);
		return daysGreaterTenHours;
	
	}
}
